package cn.chenfeifx.core.controls;

import cn.chenfeifx.core.common.AnimationUtils;
import cn.chenfeifx.core.common.ResourcesLoader;
import javafx.animation.Timeline;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.WritableValue;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

/**
 * 未写完
 */
public class CFNotification {

    private static final String STYLE_SHEET = ResourcesLoader.load("/cn/chenfeifx/core/css/cf-notification.css");
    private static final CFNotification instance = new CFNotification();
    private final Stage emptyStage = new Stage(); // 提供一个空的窗口
    private final Stage notificationStage = new Stage();

    /******************************* 内容节点 *******************************/
    private final Header header;
    private final BorderPane container;

    // 动画
    private Timeline parallel;

    private CFNotification() {
        header = new Header("Title", event -> {

        });
        container = new BorderPane(null, header, null, null, null);
        initialize();
    }

    public static CFNotification getInstance() {
        return instance;
    }

    private void initialize() {
        // 初始化 emptyStage
        emptyStage.setScene(new Scene(new StackPane(), 1, 1));
        emptyStage.setX(Double.MAX_VALUE);
        emptyStage.initStyle(StageStyle.UTILITY);
        // 初始化 notificationStage 内容
        header.getStyleClass().add("header");
        container.getStyleClass().add("cf-notification");
        notificationStage.setOpacity(0); // 初始化透明度
        notificationStage.initOwner(emptyStage);
        notificationStage.initStyle(StageStyle.TRANSPARENT);
        notificationStage.setAlwaysOnTop(true);
        Scene scene = new Scene(container);
        scene.setFill(null);
        scene.getStylesheets().add(STYLE_SHEET);
        notificationStage.setScene(scene);
        // animation bind
        button.layoutXProperty()
                .addListener((observable, oldValue, newValue) -> notificationStage.setX(newValue.doubleValue()));
        // 动画显示通知窗口
        notificationStage.setOnShown(event -> play());
        // 鼠标移入暂停动画
        container.hoverProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue) {
                parallel.pause();
            } else {
                parallel.play();
            }
        });
    }

    private final Button button = new Button();

    private void play() {
        Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
        double y = visualBounds.getMaxY() - notificationStage.getHeight();
        double x = visualBounds.getMaxX();
        double toX = x - notificationStage.getWidth();
        switch (getPos()) {
            case TOP_LEFT -> {
                y = visualBounds.getMinY();
                x = visualBounds.getMinX() - notificationStage.getWidth();
                toX = visualBounds.getMinX();
            }
            case TOP_RIGHT -> {
                y = visualBounds.getMinY();
                x = visualBounds.getMaxX();
            }
            case BOTTOM_LEFT -> {
                x = visualBounds.getMinX() - notificationStage.getWidth();
                toX = visualBounds.getMinX();
            }
            case BOTTOM_RIGHT -> x = visualBounds.getMaxX();
            default -> {
            }
        }
        notificationStage.setY(y);
        notificationStage.setX(x);
        parallel = AnimationUtils.parallel(Duration.millis(250),
                new WritableValue[]{notificationStage.opacityProperty(), button.layoutXProperty()},
                new Object[]{0, x},
                new Object[]{1, toX},
                event1 -> {
                    emptyStage.hide(); // 关闭窗口
                },
                true,
                Duration.seconds(2.5)
        );
        parallel.play();
    }

    public void show() {
        if (!emptyStage.isShowing()) {
            emptyStage.setOnShown(event -> notificationStage.show());
            emptyStage.show();
        } else {
            notificationStage.show();
        }
    }

    public StringProperty titleProperty() {
        return this.header.titleProperty();
    }

    public void setTitle(String title) {
        this.header.titleProperty().set(title);
    }

    public String getTitle() {
        return header.titleProperty().get();
    }

    // 位置
    private final ObjectProperty<Pos> pos = new SimpleObjectProperty<>(Pos.BOTTOM_RIGHT);

    public ObjectProperty<Pos> posProperty() {
        return pos;
    }

    public Pos getPos() {
        return pos.get();
    }

    public void setPos(Pos pos) {
        this.pos.set(pos);
    }

    // 内容
    public ObjectProperty<Node> contentProperty() {
        return container.centerProperty();
    }

    public Node getContent() {
        return container.getCenter();
    }

    public void setContent(Node node) {
        this.container.setCenter(node);
    }

    public void setContentText(String text) {
        Label textLabel = new Label(text);
        textLabel.getStyleClass().add("text-label");
        this.container.setCenter(textLabel);
    }

    public enum Pos {
        BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT,
    }
}
